package com.namo.cchapi.service.impl;

import com.baidu.aip.ocr.AipOcr;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.namo.cchapi.consumer.FileConsumer;
import com.namo.cchapi.entity.baidu.auth.BaiduAccessToken;
import com.namo.cchapi.entity.baidu.ocr.IdCardEntity;
import com.namo.cchapi.service.OcrService;
import com.namo.cchapi.service.RedisService;
import com.namo.cchapi.util.MockMultipartFile;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
/**
 * @author WangXin
 * @date 2021/4/10 14:49
 */
@Service
@Slf4j
@RefreshScope
public class OcrServiceImpl implements OcrService {
    @Autowired
    AipOcr aipOcr;
    @Autowired
    RestTemplate restTemplate;
    @Autowired
    Gson gson;
    @Autowired
    RedisService redisService;
    @Autowired
    FileConsumer fileConsumer;

    /**
     *OCR
     */
    @Value("${baidu.ocr.app-id}")
    private  String OCR_APP_ID;
    @Value("${baidu.ocr.api-key}")
    private  String OCR_API_KEY;
    @Value("${baidu.ocr.secret-key}")
    private  String OCR_SECRET_KEY;
    public static final String GRANT_TYPE =  "grant_type";
    public static final String WORDS_RESULT="words_result";

    public static final String NAME =  "姓名";
    public static final String NATION =  "民族";
    public static final String ADDRESS =  "住址";
    public static final String NUMBER =  "公民身份号码";
    public static final String BIRTHDAY =  "出生";
    public static final String SEX =  "性别";



    /**
     *
     * @param image     身份证图片信息
     * @param imageType 身份证图片类型（base64或者url）
     * @param imageSide front：身份证含照片的一面；back：身份证带国徽的一面
     * @return
     * @throws Exception
     */
    @Override
    public IdCardEntity ocrIdCard(String image, String imageType, String imageSide) throws Exception {
        // TODO: 2021/4/11 日志处理
        Map<String, String> requestParam = new HashMap<>();
        requestParam.put("access_token", this.getAccessToken().getAccessToken());
        //图片完整URL，URL长度不超过1024字节，URL对应的图片base64编码后大小不超过4M，最短边至少15px，最长边最大4096px,支持jpg/jpeg/png/bmp格式，当image字段存在时url字段失效
        requestParam.put("url",image);
        //-front：身份证含照片的一面
        //-back：身份证带国徽的一面
        requestParam.put("id_card_side",imageSide);
        //设置返回身份证头像base64图片
        requestParam.put("detect_photo","true");
        //是否开启身份证风险类型(身份证复印件、临时身份证、身份证翻拍、修改过的身份证)功能
        requestParam.put("detect_risk","true");
        //请求返回字符串
        String res =null;
        try {
            res = restTemplate.postForObject("https://aip.baidubce.com/rest/2.0/ocr/v1/idcard?access_token={access_token}&url={url}&id_card_side={id_card_side}&detect_photo={detect_photo}&detect_risk={detect_risk}", null, String.class, requestParam);
        } catch (RestClientException e) {
            log.error("百度ocr的AccessToken请求错误"+ e.getLocalizedMessage());
        }
        JsonObject jsonObject = gson.fromJson(res, JsonObject.class);
        //判断返回是否正确
        if (jsonObject.has(WORDS_RESULT)==false || jsonObject.getAsJsonObject(WORDS_RESULT).has(NAME) == false){
            log.error("识别失败=>"+jsonObject.toString());
            throw new Exception("识别失败！");
        }
        JsonObject wordsResultObject = jsonObject.getAsJsonObject("words_result");
        IdCardEntity idCardEntity = new IdCardEntity();
        idCardEntity.setName(wordsResultObject.getAsJsonObject(NAME).get("words").getAsString());
        idCardEntity.setNation(wordsResultObject.getAsJsonObject(NATION).get("words").getAsString());
        idCardEntity.setAddress(wordsResultObject.getAsJsonObject(ADDRESS).get("words").getAsString());
        idCardEntity.setNumber(wordsResultObject.getAsJsonObject(NUMBER).get("words").getAsString());
        idCardEntity.setBirthday(wordsResultObject.getAsJsonObject(BIRTHDAY).get("words").getAsString());
        idCardEntity.setSex(wordsResultObject.getAsJsonObject(SEX).get("words").getAsString());
        String photo = jsonObject.get("photo").getAsString();
        //解码base64
        byte[] bytes = Base64.getDecoder().decode(photo);
        //构造MultipartFile
        MultipartFile multipartFile = new MockMultipartFile("test", "test.jpg", "image/jpeg",bytes);
        //上传头像图片
        String fileUpResult = null;
        try {
            fileUpResult =  fileConsumer.upPic(multipartFile);
        }catch (Exception e){
            throw new Exception("头像图片转存失败！");
        }
        JsonObject fileUpResultJson = gson.fromJson(fileUpResult,JsonObject.class);
        //设置身份证照片链接
        idCardEntity.setAvatar(fileUpResultJson.getAsJsonObject("data").get("url").getAsString());
        return idCardEntity;
    }
    /**
     * 获取ocr的AccessToken
     * @return
     * @throws Exception
     */
    public BaiduAccessToken getAccessToken() throws Exception {
        BaiduAccessToken baiduAccessToken = null;
        //从缓存中查询是否有数据
        baiduAccessToken = (BaiduAccessToken)redisService.get("cch:baidu-ocr-auth");
        //redis命中场景
        if (baiduAccessToken != null) {
            log.info("百度ocr的AccessToken缓存命中");
            Long nowTime = System.currentTimeMillis();
            Long createTime = baiduAccessToken.getCreateTime();
            //缓存未过期
            if (nowTime < createTime + baiduAccessToken.getExpiresIn()) {
                log.info("数据未过期=>返回数据（getAccessToken执行完毕）");
                return baiduAccessToken;
            } else {
                log.info("数据过期");
            }
        }
        //重新获取accessToken
        log.info("获取百度AccessToken=>发送请求获取");
        //发送请求
        Map<String, String> requestParam = new HashMap<>();
        requestParam.put("grant_type", GRANT_TYPE);
        requestParam.put("client_id", OCR_API_KEY);
        requestParam.put("client_secret",OCR_SECRET_KEY);
        //请求返回字符串
        String res =null;
        try {
            res = restTemplate.postForObject("https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={client_id}&client_secret={client_secret}", null, String.class, requestParam);
        } catch (RestClientException e) {
            log.error("百度ocr的AccessToken请求错误"+ e.getLocalizedMessage());
            throw new Exception("api请求错误");
        }
        //设置返回对象
        baiduAccessToken = gson.fromJson(res,BaiduAccessToken.class);
        baiduAccessToken.setExpiresIn(baiduAccessToken.getExpiresIn() * 1000);
        baiduAccessToken.setCreateTime(System.currentTimeMillis());
        //请求成功设置缓存
        log.info("设置百度ocr的AccessToken缓存");
        redisService.set("cch:baidu-ocr-auth", baiduAccessToken);
        log.info("getAccessToken执行完毕");
        return baiduAccessToken;
    }
}
